package com.taobao.wolfwolf.taobao;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.taobao.wolfwolf.hibernate.pojo.Category;
import com.taobao.wolfwolf.hibernate.pojo.Color;
import com.taobao.wolfwolf.hibernate.pojo.ComposeColor;
import com.taobao.wolfwolf.hibernate.pojo.Type;
import com.taobao.wolfwolf.hibernate.service.CategoryService;
import com.taobao.wolfwolf.hibernate.service.ColorService;
import com.taobao.wolfwolf.hibernate.service.ComposeColorService;
import com.taobao.wolfwolf.hibernate.service.TypeService;
import com.taobao.wolfwolf.util.ApplicationContextUtil;

/**
 * 淘宝的SKU解析类
 * SKU包括商品品种,商品颜色,商品规格
 * @author Tux
 *
 * 创建时间: 2011-7-24 上午11:29:21
 * 修改时候: 2011--10-21 下午 23:30:33
 */
public class SkuParse {
	
	// 颜色
	private static final String COLORKEYWORDS = "灰|蓝|咖啡|红|粉|黄|白|绿|印花|黑|金|银|青玉|藕|紫|裸|槟";
	
	// 扣饰类别
	private static final String PIN = "胸针|发夹|发卡|发叉梳";
	
	// 蝴蝶结层数
	private static final String LAYERS = "单层|双层";
	
	// 蝴蝶结类别
	private static final String TYPES = "鞋花|头饰|衣饰";
	
	// 蝴蝶结材料
	private static final String MATERIAL = "蒙纱|缎带|罗纹";
	
	// 不良品
	private static final String REJECT = "瑕疵|溢胶|歪斜";
	
	public static final String[] SKUTITLE = {"颜色", "类型", "层数", "加钻", "原材料", "扣饰", "不良品", "规格"};

	/**
	 * 按行解析
	 * @param fileName
	 * @throws IOException
	 */
	public void parse(String fileName) throws IOException {
		BufferedReader reader = readFile(fileName);    
		String tempString = null;  
		
		int i = 0;
		String color, type, specs, layer, jewel, material, pin, reject, colorRegEx, typeRegEx, layerRegEx, rejectRegEx, materialRegEx, pinRegEx, specsRegEx = "";
		
		colorRegEx = "[\u4e00-\u9fa5]*(" + COLORKEYWORDS + ")[色]?";
		pinRegEx = "(" + PIN + ")";
		layerRegEx = "(" + LAYERS + ")";
		typeRegEx = "(" + TYPES + ")";
		materialRegEx = "(" + MATERIAL + ")";
		specsRegEx = "(\\w*\\*\\w*cm|\\d+[\\u4e00-\\u9fa5]*高|高度\\d+[\\u4e00-\\u9fa5]*|宽\\w*\\x20高\\w*|\\w+[\\u4e00-\\u9fa5]*宽)";
		rejectRegEx = "(" + REJECT + ")";
		
		while ((tempString = reader.readLine()) != null) {  
			String[] c = spiltBySku(tempString);
			String[] d = c[1].split(" ");
			int length = d.length;
			
			color = getValue(tempString, colorRegEx);
			type = getValue(tempString, typeRegEx);
			layer = getValue(tempString, layerRegEx);
			material = getValue(tempString, materialRegEx);
			pin = getValue(tempString, pinRegEx);
			specs = getValue(tempString, specsRegEx);
			reject = getValue(tempString, rejectRegEx);
			jewel = getValue(tempString, "钻");
			
			if(specs != null) {
				System.out.println(width(hwidth(specs)));
			}
		}
		System.out.println(width(hwidth("高度28毫米")));
		width("h45毫米");
		reader.close();  
	}
	
	/**
	 * {"颜色", "类型", "层数", "加钻", "原材料", "扣饰", "不良品", "规格"}
	 * 根据解析好的属性返回SKU
	 * @param m
	 * @return
	 * 		SKU类 其中包括类型或者颜色
	 */
	public static Sku getSku(String property) {
		Map<String, String> m = parseProperty(property);
		
		ComposeColor ccolor = null;
		Color color = null;
		Type type = null;
		String specs = null;
		
		for(int i = 0; i < SkuParse.SKUTITLE.length; i++) {
			String sku_title = SkuParse.SKUTITLE[i];
			String sku_value = m.get(sku_title);
			
			if(sku_value != null) {
				switch(i) {
				case 0:
					ComposeColorService csc = (ComposeColorService) ApplicationContextUtil.getBean("ComposeColorService");
					ColorService cs = (ColorService) ApplicationContextUtil.getBean("ColorService");
					color = cs.findByName(sku_value).isEmpty() ? null : cs.findByName(sku_value).get(0);
					if(color == null) {
						color = new Color(sku_value);
						cs.create(color);
					}
					
					ccolor = csc.findColor(color);
					
					if(ccolor == null) {
						ccolor = new ComposeColor();
						ccolor.setButtom_color(color);
					}
					
					break;
				case 3:
					break;
				case 7:
					specs = m.get(sku_title);
					break;
				default:
					TypeService ts = (TypeService) ApplicationContextUtil.getBean("TypeService");
					CategoryService gs = (CategoryService) ApplicationContextUtil.getBean("CategoryService");
					type = ts.findByName(sku_value).isEmpty() ? null : ts.findByName(sku_value).get(0);
					if(type == null) {
						Category category = gs.findByName(SkuParse.SKUTITLE[i]).isEmpty() ? null : gs.findByName(SkuParse.SKUTITLE[i]).get(0);
						
						if(category == null) {
							category = new Category(SkuParse.SKUTITLE[i]);
						}
						type = new Type(sku_value);
						type.setCategory(category);
						ts.create(type);
					}
					
					break;
				}
			}
			
		}
		
		Sku sku = new SkuParse.Sku(ccolor, type);
		if(specs != null) {
			sku.setSpecs(specs);
		}
		return sku;
	}
	
	/**
	 * 解析属性
	 * @param property
	 * @return
	 * 	<b>数组:</b>
	 * <p> 
	 * { 颜色, 蝴蝶结类型(鞋花|头饰), 蝴蝶结层数, 是否有钻, 蝴蝶结原料类型, 扣饰类型, 是否为不良品, 规格 }
	 * </p>
	 */
	private static Map<String, String> parseProperty(String property) {
		String color = null, type, specs, layer, jewel, material, pin, reject, colorRegEx, typeRegEx, layerRegEx, rejectRegEx, materialRegEx, pinRegEx, specsRegEx = "";
		
		// 匹配颜色的正则式
		colorRegEx = "[\u4e00-\u9fa5]*(" + COLORKEYWORDS + ")[色]?";
		
		// 匹配扣饰的正则式
		pinRegEx = "(" + PIN + ")";
		
		// 匹配层数的正则式
		layerRegEx = "(" + LAYERS + ")";
		
		// 匹配类型的正则式
		typeRegEx = "(" + TYPES + ")";
		
		// 匹配材料的正则式
		materialRegEx = "(" + MATERIAL + ")";
		
		// 匹配不良品的正则式
		rejectRegEx = "(" + REJECT + ")";
		
		// 匹配规格的正则式
		specsRegEx = "(\\w*\\*\\w*cm|\\d+[\\u4e00-\\u9fa5]*高|高度\\d+[\\u4e00-\\u9fa5]*|宽\\w*\\x20高\\w*|\\w+[\\u4e00-\\u9fa5]*宽)";
		
		// 商品颜色
		if(getValue(property, colorRegEx) != null)
			color = formateColor(getValue(property, colorRegEx));
		
		// 商品类别
		type = getValue(property, typeRegEx);
		layer = getValue(property, layerRegEx);
		material = getValue(property, materialRegEx);
		pin = getValue(property, pinRegEx);
		reject = getValue(property, rejectRegEx);
		jewel = getValue(property, "钻");
		
		specs = null;
		
		// 商品规格
		String v = getValue(property, specsRegEx);
		if(v != null)
			specs = width(hwidth(v));
		
		return setMap(new String[]{color, type, layer, jewel, material, pin, reject, specs});
	}
	
	private static String formateColor(String color) {
		if(!color.contains("色")) {
			return color + "色";
		}
		return color;
	}
	
	private static Map<String, String> setMap(String[] sku) {
		
		Map<String, String> map = new HashMap<String, String>();
		
		for(int i = 0; i < sku.length; i++) {
			if(sku[i] != null)
				map.put(SKUTITLE[i], sku[i]);
		}
		
		return map;
	}
	
	private static String getValue(String str, String regEx) {
		Matcher m = null;
		
		Pattern p = Pattern.compile(regEx);
		m = p.matcher(str);
		
		if(m.find()) {
			return str.substring(m.start(), m.end());
		}
		return null;
	}
	
	/**
	 * 拼装格式化规格尺寸
	 * w * h 正常情况
	 * w * 只有宽的情况
	 * * h 只有高的情况
	 * @param str
	 * @param shape
	 */
	private static String hwidth(String str) {
		
		// 匹配正则式: 高度28毫米
		if(str.matches("高度\\d+[\\u4e00-\\u9fa5]*")) {
			return "h" + getValue(str, "\\d*毫米");
		} 
		
		// 匹配正则式: 46厘米高
		else if(str.matches("\\w+[\\u4e00-\\u9fa5]*高")) {
			return "h" + getValue(str, "\\w+[\\u4e00-\\u9fa5]*[^高]");
		} 
		
		// 匹配正则式: 下摆最宽12 高9cm
		else if(str.matches("宽\\w*\\x20高\\w*[\\u4e00-\\u9fa5]*")) {
			String h = getValue(str, "\\w+$");
			String w = getValue(str, "宽\\w+[\\u4e00-\\u9fa5]*");
			
			w = getValue(w, "\\w+[\\u4e00-\\u9fa5]*");
			
			return w + "*" + h;
		} 
		
		// 匹配正则式: 13cm宽
		else if(str.matches("\\w+[\\u4e00-\\u9fa5]*宽")) {
			String s = "w" + getValue(str, "\\w+[\\u4e00-\\u9fa5]*[^宽]");
			return s;
		} 
		
		// 匹配正则式: 13*14cm 13cm*13cm
		else {
			return str;
		}
	}
	
	/**
	 * 格式化规格尺寸
	 * 使其成为: 10cm*20cm这种格式
	 * w * h 正常情况
	 * w * 只有宽的情况
	 * * h 只有高的情况
	 * @param width
	 * 		格式化后的规格尺寸
	 */
	private static String width(String width) {
		// 28*110cm, 14cm*16cm, 13cm, 20mm, 46厘米, 9cm, w9cm ,h9cm, 19*32cm, 13*cm
		
		String unit = "";
		
		// h30cm
		if(width.contains("h")) {
			width = formatWidth(width, 'h');
			unit = width.replace('h', '*');
		} 
		// w35cm
		else if(width.contains("w")) {
			width = formatWidth(width, 'w');
			unit = width.replace('w', ' ').trim() + "*";
		} 
		// 35*55cm 35cm*55cm
		else {
			String[] widths = width.split("\\*");
			
			for(int i = 0; i < widths.length; i ++) {
				// 如果数组 i 里没有cm单位,则加上cm
				if(!widths[i].contains("cm")) {
					widths[i] = widths[i] + "cm";
				}
			}
			
			unit = widths[0] + "*" + widths[1];
		}
		return unit;
	}
	
	private static String formatWidth(String width, char c) {
		if(width.contains("cm")) {
			
		} else if(width.contains("mm") || width.contains("毫米")) {
			int w = Integer.valueOf(getValue(width, "\\d+")) / 10;
			width = c + String.valueOf(w) + "cm";
		} if(width.contains("厘米")) {
			width = width.replace("厘米", "cm");
		} if(width.matches("毫米")) {
			
		}
		
		return width;
	}
	
	/**
	 * 读取文件
	 * @param fileName
	 * 			文件名称
	 * @return
	 *			返回 BufferReader
	 * @throws IOException
	 */
	private BufferedReader readFile(String fileName) throws IOException {
		InputStreamReader irs = new InputStreamReader(new FileInputStream(fileName), "UTF-8");
		return new BufferedReader(irs);
	}
	
	private String[] spiltBySku(String s) {
		String[] a = s.split(":");
		String[] b = {a[0] + ":" + a[1], a[2]};
		return b;
	}
	
	/**
	 * 封装sku属性的类
	 * @author qinanhg@gmail.com
	 *
	 * 创建时间: 2011-10-20 下午8:38:29
	 */
	public static class Sku {
		private Color color;
		private ComposeColor ccolor;
		private Type type;
		private String specs = null;
		
		public Sku() {
		}
		
		public Sku(ComposeColor ccolor, Type type) {
			this.ccolor = ccolor;
			this.type = type;
		}
		
		public Sku(Color color, Type type, String specs) {
			this.color = color;
			this.specs = specs;
		}

		public String getSpecs() {
			return specs;
		}

		public void setSpecs(String specs) {
			this.specs = specs;
		}

		public Color getColor() {
			return color;
		}

		public void setColor(Color color) {
			this.color = color;
		}

		public Type getType() {
			return type;
		}

		public void setType(Type type) {
			this.type = type;
		}

		public ComposeColor getCcolor() {
			return ccolor;
		}

		public void setCcolor(ComposeColor ccolor) {
			this.ccolor = ccolor;
		}

		/* (non-Javadoc)
		 * @see java.lang.Object#toString()
		 */
		@Override
		public String toString() {
			return "Sku [color=" + color + ", ccolor=" + ccolor + ", type="
					+ type + ", specs=" + specs + "]";
		}
	}
}
